package org.shangrila.app.wechat.config;

import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.SSLContext;

import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;

@Component
@Configuration
@ConditionalOnClass(value = { RestTemplate.class, HttpClient.class })
public class RestTemplateConfiguration {

	@Value("${remote.maxTotalConnect:200}")
	private static int maxTotalConnect; // 连接池的最大连接数默认为0
	@Value("${remote.maxConnectPerRoute:100}")
	private static  int maxConnectPerRoute; // 单个主机的最大连接数
	@Value("${remote.connectTimeout:2000}")
	private static  int connectTimeout; // 连接超时默认2s
	@Value("${remote.readTimeout:30000}")
	private static int readTimeout; // 读取超时默认30s
	
	public static RestTemplate restTemplate;

	// 创建HTTP客户端工厂
	@SuppressWarnings("unused")
	private static ClientHttpRequestFactory createFactory() {
		if (maxTotalConnect <= 0) {
			SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
			factory.setConnectTimeout(connectTimeout);
			factory.setReadTimeout(readTimeout);
			return factory;
		}
		
		TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;

        SSLContext sslContext = null;
		try {
			sslContext = org.apache.http.ssl.SSLContexts.custom()
			        .loadTrustMaterial(null, acceptingTrustStrategy)
			        .build();
		} catch (KeyManagementException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (KeyStoreException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);
		
		HttpClient httpClient = HttpClientBuilder.create().setSSLSocketFactory(csf).setMaxConnTotal(maxTotalConnect)
				.setMaxConnPerRoute(maxConnectPerRoute).build();
		HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
		factory.setConnectTimeout(connectTimeout);
		factory.setReadTimeout(readTimeout);
		return factory;
	}

	// 初始化RestTemplate,并加入spring的Bean工厂，由spring统一管理
	@Bean
	@ConditionalOnMissingBean(RestTemplate.class)
	public static RestTemplate getRestTemplate() {
		if(restTemplate==null) {
			restTemplate = new RestTemplate();
			List<HttpMessageConverter<?>> converterList = restTemplate.getMessageConverters();

			// 重新设置StringHttpMessageConverter字符集为UTF-8，解决中文乱码问题
			HttpMessageConverter<?> converterTarget = null;
			for (HttpMessageConverter<?> item : converterList) {
				if (StringHttpMessageConverter.class == item.getClass()) {
					converterTarget = item;
					break;
				}
			}
			if (null != converterTarget) {
				converterList.remove(converterTarget);
			}
			converterList.add(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));

			// 加入FastJson转换器
			FastJsonHttpMessageConverter fastjson = new FastJsonHttpMessageConverter();
		    
		    List<MediaType> supportedMediaTypes = new ArrayList<>();
		    supportedMediaTypes.add(MediaType.APPLICATION_JSON);
		    supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
		    supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML);
		    supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
		    supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
		    supportedMediaTypes.add(MediaType.APPLICATION_PDF);
		    supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML);
		    supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML);
		    supportedMediaTypes.add(MediaType.APPLICATION_XML);
		    supportedMediaTypes.add(MediaType.IMAGE_GIF);
		    supportedMediaTypes.add(MediaType.IMAGE_JPEG);
		    supportedMediaTypes.add(MediaType.IMAGE_PNG);
		    supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM);
		    supportedMediaTypes.add(MediaType.TEXT_HTML);
		    supportedMediaTypes.add(MediaType.TEXT_MARKDOWN);
		    supportedMediaTypes.add(MediaType.TEXT_PLAIN);
		    supportedMediaTypes.add(MediaType.TEXT_XML);
		    fastjson.setSupportedMediaTypes(supportedMediaTypes);
			converterList.add(fastjson);
		}
		return restTemplate;
	}
}
